﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SiGeSIB.GUI.Common;
using SiGeSIB.Data.Finances;
using SiGeSIB.GUI.Common.DedaGrid.Utils;
using SiGeSIB.Data.Management;
using SiGeSIB.Data.Common;
using SiGeSIB.GUI.Common.DedaGrid.Filter;
using SiGeSIB.GUI.Properties;
using SiGeSIB.Services;
using System.Globalization;

namespace SiGeSIB.GUI.Finances
{
#if DESIGN
	public partial class FManageMovimentations : FormRedirector.FManageMovimentations
#else
	public partial class FManageMovimentations : FGenericManager<Movimentation>
#endif
	{
		#region ColumnsNames
		private const string DT_DATE = "Data";
		private const string DT_MONTH = "Mês";
		private const string DT_MOVIMENTATION_TYPE = "Tipo";
		private const string DT_VALUE = "Valor";
		private const string DT_COST_CENTER = "Centro de custo";
		private const string DT_SOURCE = "Origem";
		private const string DT_TARGET = "Destino";
		private const string DT_PAYMENT_METHOD = "Forma de pagamento";
		protected const string DT_INCOME_TYPE = "Tipo entrada";
		#endregion

		# region Constructors
		public FManageMovimentations()
			: this(EMovimentationType.Income)
		{ }
		public FManageMovimentations(EMovimentationType type)
		{
			InitializeComponent();

			_Type = type;

			_CostCenters = new Dictionary<int, CostCenter>();
			
			_GroupedColumns = new List<string>() { DT_MONTH };
		}
		#endregion

		#region Attributes
		private EMovimentationType _Type;
		private DateTimeInterval _DesiredInterval;
		private Image _IncomeImage = Resources._in;
		private Image _OutcomeImage = Resources._out;
		private Dictionary<int, CostCenter> _CostCenters;
		#endregion

		#region Properties
		public EMovimentationType Type { get; set; }
		public DateTimeInterval AnalysedInterval {
			get
			{
				return _DesiredInterval;
			}
			set
			{
				_DesiredInterval = value;
				_LoadData();
			}
		}

		protected override string _Description
		{
			get
			{
				switch (Type)
				{
					case EMovimentationType.Income:
						return "as Movimentações de Entrada";
					case EMovimentationType.Outcome:
						return "as Movimentações de Saída";
					case EMovimentationType.FutureReleases:
						return "as Lançamentos Futuros";
					default:
						return "";
				}
			}
		}
		#endregion

		#region EventHandlers
		protected override void OnLoad(EventArgs e)
		{
			_AdjustColumnsVisibility();
			base.OnLoad(e);
		}

		private void _AdjustColumnsVisibility()
		{
			if (Type == EMovimentationType.FutureReleases)
				uManageDefaultToolStrip.IsAddButtonVisible = false;
		}
		protected override void uManageDefaultToolStrip_AddClicked(object sender, EventArgs e)
		{
			Manager.Instance.CreateParentTab(this, new FEditMovimentation(EFormState.Edit, Type, -1));
		}

		protected override void uManageDefaultToolStrip_EditClicked(object sender, EventArgs e)
		{
			DataRow row = uEntitiesGrid.GetSelectedRow();
			int currentId = (int)row[DT_ID];
			Movimentation mov = (Movimentation)row[DT_ITEM_HOLDER];
			EMovimentationType type = mov.Type;
			Manager.Instance.CreateParentTab(this, new FEditMovimentation(EFormState.View, type, currentId));
		} 
		#endregion

		#region Methods
		#region Loading
		protected override void _InitializeDataColumns()
		{
			_DedaColumns = new List<DedaGridColumn>()
			{
				new DedaGridColumn(DT_ID, typeof(int)) { Visible = false },
				new DedaGridColumn(DT_MONTH, typeof(string)),
				new DedaGridColumn(DT_DATE, typeof(string)),
				new DedaGridColumn(DT_MOVIMENTATION_TYPE, typeof(Image)) {Visible = (Type == EMovimentationType.FutureReleases)},
				new DedaGridColumn(DT_VALUE, typeof(string)),
				new DedaGridColumn(DT_COST_CENTER, typeof(string)),
				new DedaGridColumn(DT_SOURCE, typeof(string)) { Visible = (Type == EMovimentationType.Income)},
				new DedaGridColumn(DT_TARGET, typeof(string)) { Visible = (Type == EMovimentationType.Outcome)},
				new DedaGridColumn(DT_PAYMENT_METHOD, typeof(string)),
				new DedaGridColumn(DT_INCOME_TYPE, typeof(string)) { Visible = (Type == EMovimentationType.Income)},
				new DedaGridColumn(DT_ITEM_HOLDER, typeof(Movimentation)) { Visible = false }
			};
		}

		protected override object[] _ConvertToDataRow(Movimentation m)
		{
			if (m.CostCenter != null && !_CostCenters.ContainsKey(m.CostCenter.Id))
				_CostCenters.Add(m.CostCenter.Id, m.CostCenter);

			return new object[]
				{
					m.Id,
					m.MovimentationDate.ToString("MMMM/yyyy").FirstToUpper(),
					m.MovimentationDate.ToShortDateString(),
					m is Income ? _IncomeImage : _OutcomeImage,
					m is Income ? m.Amount.ToString(CultureInfo.InvariantCulture) : (-m.Amount).ToString(CultureInfo.InvariantCulture),
					m.CostCenter != null ? m.CostCenter.Name : (object)DBNull.Value,
					m is Income ? m.Contributor.Name : null,
					m is Outcome ? m.Contributor.Name : null,
					m.PaymentMethod.Method.GetDescription(),
					m is Income ? ((Income)m).IncomeType.GetDescription() : null,
					m
				};
		}

		protected override List<Movimentation> _LoadEntity()
		{
			if (_DesiredInterval == null)
			{
				if (Type == EMovimentationType.FutureReleases)
					_DesiredInterval = new DateTimeInterval(DateTime.Today.AddDays(1).Truncate(), null);
				else
					_DesiredInterval = new DateTimeInterval(null, DateTime.Today.Truncate());
			}

			IFinancesServicesProvider finProv = Manager.Instance.ServicesProvider.CreateFinancesServicesProvider();

			List<Movimentation> movimentations = null;
			MovimentationFilter filter = new MovimentationFilter();
			filter.DesiredInterval = _DesiredInterval;

			if (Type != EMovimentationType.FutureReleases)
			{
				filter.DesiredType = Type;
			}

			movimentations = finProv.GetMovimentations(filter, MovimentationInfo.SpecificData);

			return movimentations;
		}
		#endregion

		protected override bool _RequestRemove()
		{
			return MessageBox.Show(this, "Deseja remover a movimentação selecionada?", "Confirmação", MessageBoxButtons.OKCancel) == DialogResult.OK;
		}

		protected override void _ApplyFilter(string p)
		{
			DedaGridFilterCollection collection = new DedaGridFilterCollection();
			collection.Add(new DedaGrigFilterCondition(_DtTable.Columns[DT_DATE], ELogicalCondition.CONTAINS, p));
			collection.Add(new DedaGrigFilterCondition(EDedaGridFilterLogicalConnector.OR, _DtTable.Columns[DT_VALUE], ELogicalCondition.CONTAINS, p));
			collection.Add(new DedaGrigFilterCondition(EDedaGridFilterLogicalConnector.OR, _DtTable.Columns[DT_COST_CENTER], ELogicalCondition.CONTAINS, p));
			collection.Add(new DedaGrigFilterCondition(EDedaGridFilterLogicalConnector.OR, _DtTable.Columns[DT_SOURCE], ELogicalCondition.CONTAINS, p));
			collection.Add(new DedaGrigFilterCondition(EDedaGridFilterLogicalConnector.OR, _DtTable.Columns[DT_TARGET], ELogicalCondition.CONTAINS, p));
			collection.Add(new DedaGrigFilterCondition(EDedaGridFilterLogicalConnector.OR, _DtTable.Columns[DT_PAYMENT_METHOD], ELogicalCondition.CONTAINS, p));
			collection.Add(new DedaGrigFilterCondition(EDedaGridFilterLogicalConnector.OR, _DtTable.Columns[DT_INCOME_TYPE], ELogicalCondition.CONTAINS, p));

			_DtTable.Filter(collection);
		}

		protected override void _RemoveEntity(int id)
		{
			IFinancesServicesProvider finProv = Manager.Instance.ServicesProvider.CreateFinancesServicesProvider();
			finProv.RemoveMovimentation(id);
		}

        #region public
        public void ExportMovimentations(string filePath)
        {
            if (!_Controller.IsBusy)
            {
                _Controller.EnableBusy();
                bwReport.RunWorkerAsync(filePath);
            }
        }

        public void SetInterval(DateTimeInterval interval)
        {
            _DesiredInterval = interval;
        } 
        #endregion

        #region Report
        private void bwReport_DoWork(object sender, DoWorkEventArgs e)
        {
            string filePath = e.Argument as string;

            if (filePath != null)
            {
                IReportServicesProvider repServ = _Manager.ServicesProvider.CreateReportServicesProvider();

                repServ.GenerateReport(_CostCenters.Select(pair => pair.Value).ToList(), filePath, Type, AnalysedInterval);
            }
        }

        private void bwReport_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (!IsDisposed)
            {
                _Controller.ClearErrors();
                _Controller.DisableBusy();

                if (e.Error == null)
                {
                    MessageBox.Show(this, "A exportação foi concluída com sucesso.", "Exportação", MessageBoxButtons.OK);
                }
                else
                    throw e.Error;
            }
        } 
        #endregion
        #endregion
    }
}
